package com.king.juc.n7;

import lombok.extern.slf4j.Slf4j;

import java.sql.Connection;
import java.util.concurrent.atomic.AtomicIntegerArray;

/**
 * DIY简易连接池
 *      享元模式
 *      欠缺:
 *          连接的动态增长与收缩
 *          连接活性(可用性检测)
 *          等待超时处理
 *          分布式hash
 * @author king
 * @date 2020/12/6 22:34
 */
@Slf4j(topic = "c.Pool")
public class Pool {

    /**
     * 连接池大小
     */
    private final int poolSize;
    /**
     * 连接对象数组
     */
    private Connection[] connections;
    /**
     * 连接状态数组 0: 空闲 1: 繁忙
     */
    private AtomicIntegerArray states;

    public Pool(int poolSize) {
        this.poolSize = poolSize;
        this.connections = new Connection[poolSize];
        this.states = new AtomicIntegerArray(new int[poolSize]);

        // 初始化链接对象
        for (int i = 0; i < poolSize; i++) {
            connections[i] = new MockConnection("连接" + (i + 1));
        }
    }

    /**
     * 借连接
     */
    public Connection borrow() {
        while (true) {
            for (int i = 0; i < poolSize; i++) {
                // 获取空闲连接
                if (states.get(i) == 0 && states.compareAndSet(i, 0, 1)) {
                    log.debug("获取连接{}", connections[i]);
                    return connections[i];
                }
            }

            // 没有空闲连接, 当前线程进入等待
            synchronized (this) {
                try {
                    log.debug("等待....");
                    this.wait();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    /**
     * 归还连接
     */
    public void free(Connection conn) {
        for (int i = 0; i < poolSize; i++) {
            if(connections[i] == conn) {
                log.debug("归还连接{}", connections[i]);
                states.set(i, 0);
                synchronized (this) {
                    this.notifyAll();
                }
                break;
            }
        }
    }
}
